#include "encoder.h"
#include "ti/devices/msp/peripherals/hw_i2c.h"
#include <stdbool.h>

#define I2C_ENCODER_ADDRESS (0x01)
//上面那个去ti_msp_dl_config里面找 如果不是 I2C_0_INST的话改成那个是的
/*
1.基本功能全部写完
2.需要其他功能的话已经不涉及I2C通信的问题了
3.有时间可以写一下如果超时的处理函数，不过目前这些功能也够用了
4.需要添加软件I2C通信的功能
*/
void Init_I2c_Encoder_Reg(I2C_ENCODER_REG *reg,I2C_Regs *i2c,uint32_t targetAddr)  //声明变量之后要在这里面初始化一下
{
    reg->op.i2c=i2c;
    reg->op.targetAddr=targetAddr;
    //这边写一些结构体里变量的初始化
    reg->Set_LED_Reg[0]=0xff;
    reg->Set_LED_Reg[1]=0xff;
    reg->Set_GPIO_Station[0]=0x80;
    reg->Set_GPIO_Station[1]=0x80;
    reg->Set_GPIO_OUTPUT[0]=0x80;
    reg->Set_GPIO_OUTPUT[1]=0x80;
    reg->Read_GPIO_Stat=0x00;
}

uint8_t *Read_TIM1(I2C_ENCODER_REG * reg) {

  reg->Set_rw_reg=I2C_ENCODER_READ_TIM1; //寄存器地址
  reg->op.buffer=(uint8_t *)&reg->TIM1_reg;
  reg->op.count=3;
  reg->op.set_reg=reg->Set_rw_reg;

  I2C_Receive_Poll(&reg->op);
  return (uint8_t *)&reg->TIM1_reg; //返回TIM_REG的地址
}

uint8_t *Read_TIM2(I2C_ENCODER_REG * reg) {

  reg->Set_rw_reg=I2C_ENCODER_READ_TIM2; //寄存器地址
  reg->op.buffer=(uint8_t *)&reg->TIM2_reg;
  reg->op.count=3;
  reg->op.set_reg=reg->Set_rw_reg;

  I2C_Receive_Poll(&reg->op);
  return (uint8_t *)&reg->TIM2_reg; //返回TIM_REG的地址
}

uint8_t *Read_TIM_ALL(I2C_ENCODER_REG * reg) {

  reg->Set_rw_reg=I2C_ENCODER_READ_ALL; //寄存器地址
  reg->op.buffer=(uint8_t *)&reg->TIM_reg;
  reg->op.count=6;
  reg->op.set_reg=reg->Set_rw_reg;

  I2C_Receive_Poll(&reg->op);
  return (uint8_t *)&reg->TIM_reg; //返回TIM_REG的地址
}
int16_t Get_TIM1(I2C_ENCODER_REG *reg)
{
    uint8_t *data_temp;
    data_temp=Read_TIM1(reg);
    return (data_temp[0]<<8|data_temp[1]);
}

int16_t Get_TIM2(I2C_ENCODER_REG *reg)
{
    uint8_t *data_temp;
    data_temp=Read_TIM2(reg);
    return (data_temp[0]<<8|data_temp[1]);
}

int16_t *Get_TIM_ALL(I2C_ENCODER_REG *reg) //返回的是指针的地址
{
    uint8_t *data_temp;
    data_temp=Read_TIM_ALL(reg);
    reg->TIM_ALL[0]=(data_temp[0]<<8|data_temp[1]);
    reg->TIM_ALL[1]=(data_temp[2]<<8|data_temp[3]);
    return (int16_t *)&reg->TIM_ALL; //不用管这个返回的就是地址
}

uint8_t Set_LED_Reg(I2C_ENCODER_REG *reg) //0关闭1打开
{

    reg->Set_rw_reg=I2C_ENCODER_RW_LED_SWITCH; //设置控制LED模式
    reg->op.count=2; //先写两个数据 包括了REG
    reg->op.use_reg_flag=1; //寄存器地址操作开启
    reg->op.set_reg=reg->Set_rw_reg;
    if (reg->Set_LED) {
        reg->Set_LED_Reg[0]=0xFF;
    }else {
        reg->Set_LED_Reg[0]=0x00;
    }
    reg->op.buffer=(uint8_t *)&reg->Set_LED_Reg;
    if (I2C_Send_Poll(&reg->op)<0) {
        return 100; //发送错误
    }
    reg->op.count=1;
    reg->op.buffer=&reg->Set_LED_Reg[1];
    if (I2C_Read_Poll(&reg->op)<0) {
        return 200; //读取错误
    }
    if (reg->Set_LED_Reg[0]!=reg->Set_LED_Reg[1]) { //确认一下设置是否成功
        return 1;
    }
    return 0;
}
uint8_t Set_GPIO_Station(I2C_ENCODER_REG *reg,uint8_t i)
{
    reg->Set_rw_reg=I2C_ENCODER_RW_GPIO_STATION; //设置控制LED模式
    reg->op.count=2; //先写两个数据 包括了REG
    reg->op.use_reg_flag=1; //寄存器地址操作开启
    reg->op.set_reg=reg->Set_rw_reg;
    reg->Set_GPIO_Station[0] = i;
    reg->op.buffer=(uint8_t *)&reg->Set_GPIO_Station;
    if (I2C_Send_Poll(&reg->op)<0) {
        return 100; //发送错误
    }
    reg->op.count=1;
    reg->op.buffer=&reg->Set_GPIO_Station[1];
    if (I2C_Read_Poll(&reg->op)<0) {
        return 200; //读取错误
    }
    if (reg->Set_GPIO_Station[0]!=reg->Set_GPIO_Station[1]) { //确认一下设置是否成功
        return 1;
    }
    return 0;
}

uint8_t Set_GPIO_OUTPUT(I2C_ENCODER_REG *reg,uint8_t i)
{
    reg->Set_rw_reg=I2C_ENCODER_RW_GPIO_SET_OUTPUT; //设置控制LED模式
    reg->op.count=2; //先写两个数据 包括了REG
    reg->op.use_reg_flag=1; //寄存器地址操作开启
    reg->op.set_reg=reg->Set_rw_reg;
    reg->Set_GPIO_OUTPUT[0] = i;
    reg->op.buffer=(uint8_t *)&reg->Set_GPIO_OUTPUT;
    if (I2C_Send_Poll(&reg->op)<0) {
        return 100; //发送错误
    }
    reg->op.count=1;
    reg->op.buffer=&reg->Set_GPIO_OUTPUT[1];
    if (I2C_Read_Poll(&reg->op)<0) {
        return 200; //读取错误
    }
    if (reg->Set_GPIO_OUTPUT[0]!=reg->Set_GPIO_OUTPUT[1]) { //确认一下设置是否成功
        return 1;
    }
    return 0;
}

uint8_t Read_GPIO_Station(I2C_ENCODER_REG *reg)
{
    reg->Set_rw_reg=I2C_ENCODER_READ_GPIO; //寄存器地址 
    reg->op.buffer=(uint8_t *)&reg->Read_GPIO_Stat;
    reg->op.count=1;
    reg->op.set_reg=reg->Set_rw_reg;

    if (I2C_Receive_Poll(&reg->op)) {
    return 0;
    }
    return reg->Read_GPIO_Stat; //返回TIM_REG的地址
}









//结构体在h文件里面

// 返回值说明:
// 0: 正常
// -1: IIC设备不存在或者地址没有应答
// -2: 总线仲裁失败
// -3: 超时
// -4: TIMEOUT SCL拉低时间过长(需要配置并打开上面的define)
int8_t I2C_Send_Poll(I2C_Operation *op)
{
    int timeout = 50000;
    uint32_t gTxCount = 0;
    bool toolong = false;

    // 等待I2C总线空闲
    while (!(DL_I2C_getControllerStatus(op->i2c) & DL_I2C_CONTROLLER_STATUS_IDLE))
    {
        if (--timeout < 0) {
            return -3; // 超时
        }
    }

    DL_I2C_flushControllerTXFIFO(op->i2c); // 清理FIFO

    if (op->use_reg_flag) {
        DL_I2C_transmitControllerData(op->i2c, op->set_reg);
    }

    gTxCount = DL_I2C_fillControllerTXFIFO(op->i2c, op->buffer, op->count);
    toolong = (gTxCount < op->count);

    while (!(DL_I2C_getControllerStatus(op->i2c) & DL_I2C_CONTROLLER_STATUS_IDLE));
    DL_I2C_startControllerTransfer(op->i2c, op->targetAddr, DL_I2C_CONTROLLER_DIRECTION_TX, op->count);

    if (toolong) {
        while (gTxCount < op->count) {
            if (DL_I2C_getControllerStatus(op->i2c) & DL_I2C_CONTROLLER_STATUS_ERROR) {
                DL_I2C_flushControllerTXFIFO(op->i2c);
                return -1;
            }
            if (DL_I2C_getControllerStatus(op->i2c) & DL_I2C_CONTROLLER_STATUS_ARBITRATION_LOST) {
                DL_I2C_flushControllerTXFIFO(op->i2c);
                return -2;
            }
            if (DL_I2C_isControllerTXFIFOEmpty(op->i2c)) {
                gTxCount += DL_I2C_fillControllerTXFIFO(op->i2c, &(op->buffer[gTxCount]), op->count - gTxCount);
            }
        }
    }

    while (DL_I2C_getControllerStatus(op->i2c) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
    
#ifdef __ENABLE_I2C_TIMEOUT_A
    if (DL_I2C_isTimeoutAEnabled(op->i2c) && (op->i2c->CPU_INT.RIS & DL_I2C_INTERRUPT_TIMEOUT_A))
    {
        return -4;
    }
#endif

    if (DL_I2C_getControllerStatus(op->i2c) & DL_I2C_CONTROLLER_STATUS_ERROR) {
        DL_I2C_flushControllerTXFIFO(op->i2c);
        return -1;
    }
    if (DL_I2C_getControllerStatus(op->i2c) & DL_I2C_CONTROLLER_STATUS_ARBITRATION_LOST) {
        DL_I2C_flushControllerTXFIFO(op->i2c);
        return -2;
    }
    return 0;
}

// 返回值说明:
// 0: 正常
// -1: 没有收到地址
// -2: 总线仲裁失败
// -3: 等待总线发送接收超时
// -4: SCL拉低时间过长 (如果开启TIMEA的话)
int8_t I2C_Read_Poll(I2C_Operation *op)
{
    int timeout = 50000;

    while (!(DL_I2C_getControllerStatus(op->i2c) & DL_I2C_CONTROLLER_STATUS_IDLE))
    {
        if (--timeout < 0) {
            return -3;
        }
    }

    DL_I2C_flushControllerRXFIFO(op->i2c);
    DL_I2C_startControllerTransfer(op->i2c, op->targetAddr, DL_I2C_CONTROLLER_DIRECTION_RX, op->count);

    if (DL_I2C_getControllerStatus(op->i2c) & DL_I2C_CONTROLLER_STATUS_ERROR) {
        return -1;
    }
    if (DL_I2C_getControllerStatus(op->i2c) & DL_I2C_CONTROLLER_STATUS_ARBITRATION_LOST) {
        return -2;
    }

#ifdef __ENABLE_I2C_TIMEOUT_A
    if (DL_I2C_isTimeoutAEnabled(op->i2c) && (op->i2c->CPU_INT.RIS & DL_I2C_INTERRUPT_TIMEOUT_A))
    {
        return -4;
    }
#endif

    for (uint16_t i = 0; i < op->count; i++) {
        timeout = 50000;
        while (DL_I2C_isControllerRXFIFOEmpty(op->i2c) && 
               !(DL_I2C_getControllerStatus(op->i2c) & DL_I2C_CONTROLLER_STATUS_ERROR))
        {
            if (--timeout < 0) {
                return -3;
            }
        }
        op->buffer[i] = DL_I2C_receiveControllerData(op->i2c);
    }
    return 0;
}

//Backup
// 自动发送addr以及寄存器地址，并且读取需要的长度
int8_t I2C_Receive_Poll(I2C_Operation *op)
{
    int8_t sendResult, readResult;
    I2C_Operation sendOp = *op;
    uint8_t dummy = 0;

    sendOp.buffer = &dummy;
    sendOp.count = 1; //必须为1因为发了寄存器
    sendOp.use_reg_flag = true;

    sendResult = I2C_Send_Poll(&sendOp);
    if (sendResult < 0) {
        return sendResult;
    }

    readResult = I2C_Read_Poll(op);
    if (readResult < 0) {
        return readResult;
    }

    return 0;
}

//backup部分

//0 正常 -1 IIC设备不存在或者地址没有应答 -2 总线仲裁失败 -3 超时 -4 TIMEOUT SCL拉低时间过长(得去配置同时需要打开上面的define)
int8_t Backup_I2C_Send_Poll(I2C_Regs *i2c,uint32_t targetAddr,uint8_t set_reg,uint8_t *buffer,uint16_t count,int8_t use_reg_flag)  //如果返回为-1为异常0为正常
{
    //可以在这边在加一个计数时间的延迟，有时间在搞吧.
    int timeout=50000;  //时间延迟函数
    uint32_t gTxCount=0,toolong=0; //保存一下填充了多少数据到fifo里面

    while (!(DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_IDLE)) //确保上一次数据发送完成之后在清理fifo
    {
        if (timeout<0) {
            return -3; //超时
        }
        timeout--;
    }
    DL_I2C_flushControllerTXFIFO(i2c); //清理上一次fifo
    if (use_reg_flag) { //如果使用reg的话
        DL_I2C_transmitControllerData(i2c, set_reg); //先填充reg到fifo剩下的就无所谓啦！
    }
    gTxCount=DL_I2C_fillControllerTXFIFO(i2c, buffer, count); // 填充待发数据到FIFO 同时保存一下已经填充了多少数据进去

    //判断一波长不长如果不长就不进入一直填fifo的程序了
    if (gTxCount < count) {
        toolong=1;
    } 
    while (!(DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_IDLE)); // 等待I2C总线空闲
    DL_I2C_startControllerTransfer(i2c, targetAddr,DL_I2C_CONTROLLER_DIRECTION_TX,count); // 发送数据
    if (toolong) {
        while (gTxCount<count) {  //在这里等待，如果没发送完数据就一直填数据进去
            if (DL_I2C_getControllerStatus(i2c)&DL_I2C_CONTROLLER_STATUS_ERROR) {
                DL_I2C_flushControllerTXFIFO(i2c);
                return -1; //上一次地址没有应答    
            }
            if (DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_ARBITRATION_LOST) {
                DL_I2C_flushControllerTXFIFO(i2c);
                return -2;//总线仲裁失败
            }
            if (DL_I2C_isControllerTXFIFOEmpty (i2c)) {
              gTxCount+=DL_I2C_fillControllerTXFIFO(i2c,&(buffer[gTxCount]), count-gTxCount);
            }
        }
    }
    while (DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS); //等待总线空闲发送成功,如果他退不出去了就卡死在这边了,解决办法是设置计时器A
    #ifdef __ENABLE_I2C_TIMEOUT_A
    if(DL_I2C_isTimeoutAEnabled (i2c)&&(I2C_INST->CPU_INT.RIS & DL_I2C_INTERRUPT_TIMEOUT_A))
    {
        return -4;
    }
    #endif

    if (DL_I2C_getControllerStatus(i2c)&DL_I2C_CONTROLLER_STATUS_ERROR) {
        DL_I2C_flushControllerTXFIFO(i2c);
        return -1; //上一次地址没有应答    
    }
    if (DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_ARBITRATION_LOST) {
        DL_I2C_flushControllerTXFIFO(i2c);
        return -2;//总线仲裁失败
    }
    return 0;
}


//-1表示没有收到地址 -2表示总线仲裁失败 -3等待总线发送接收超时 -4 SCL拉低时间过长 如果开启TIMEA的话
int8_t Backup_I2C_Read_Poll(I2C_Regs *i2c,uint32_t targetAddr,uint8_t *buffer,uint16_t count)
{
    uint16_t i=0;
    int timecount=50000; //可以用来写延迟用。
    while (!(DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_IDLE)) //等待总线空闲
    {
        timecount--;
        if (timecount<0) {
            return -3;
        }
    }
    DL_I2C_flushControllerRXFIFO(i2c); //清理掉多余的数据
    DL_I2C_startControllerTransfer(i2c, targetAddr,DL_I2C_CONTROLLER_DIRECTION_RX, count); //要读多少个字节
    if (DL_I2C_getControllerStatus(i2c)&DL_I2C_CONTROLLER_STATUS_ERROR) {
        return -1; //上一次地址没有应答    
    }
    if (DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_ARBITRATION_LOST) {
        return -2;//总线仲裁失败
    }
    #ifdef __ENABLE_I2C_TIMEOUT_A
    if(DL_I2C_isTimeoutAEnabled (i2c)&&(I2C_INST->CPU_INT.RIS & DL_I2C_INTERRUPT_TIMEOUT_A))
    {
        return -4;
    }
    #endif
    for (i = 0; i < count; i++) {
        while (DL_I2C_isControllerRXFIFOEmpty(i2c)&&(!(DL_I2C_getControllerStatus(i2c)&DL_I2C_CONTROLLER_STATUS_ERROR)));
        buffer[i] = DL_I2C_receiveControllerData(i2c); //TIM1_H TIM1_L TIM1_circle 
    }
    return 0;
}
//自动发送addr以及寄存器地址 并且读取需要的长度
int8_t Backup_I2C_Receive_Poll(I2C_Regs *i2c,uint32_t targetAddr,uint8_t set_reg,uint8_t *buffer,uint16_t count)
{
    int8_t Send,Read;
    Send=Backup_I2C_Send_Poll(i2c, targetAddr, set_reg, buffer, 1, 1);
    Read=Backup_I2C_Read_Poll(i2c, targetAddr, buffer, count);
    if (Send<0||Read<0) { //懒得写了谁想完善一下谁完善吧
        return -1;
    }
    return 0;
}